#include "td3650clientthread.h"
#include <QDebug>
#include <QString>
#include <QTimer>
#include "tunkia.h"
#include <QHostAddress>
#include "tool.h"

TD3650ClientThread::TD3650ClientThread()
{
     qDebug()<<"TD3650线程开启了"<<QThread::currentThread();;
     错误类型=0;
     网口状态=0;
     BaudTime=50;
     timer1 = new QTimer(this);//配置TD3650连接用
     QObject::connect(timer1,&QTimer::timeout,this,[=](){TD3650ClientThread::confirmTD3650();});

     TD校准步骤=1;
//     timer2 = new QTimer(this);//校准步骤用
//     QObject::connect(timer2,&QTimer::timeout,this,[=](){TD3650ClientThread::TD3650Step();});
     TD4550输出={};
}


//getConj得到串口配置后再交由openConj打开串口
void TD3650ClientThread::getConj(QString IP地址,int IP端口)
{
    接收数据="";
    检查次数=1;
    检查步骤=1;
    TD4550输出={220000,220000,220000,0,0,0, 0,0,0, 0,0,0,  0,0,0,  0,0,0};
    //openConj(IP地址,IP端口);
    //创建客户端Socket
    server = new QTcpSocket;
    //连接服务器端
    server->connectToHost(QHostAddress(IP地址),IP端口);
    //接收服务器数据
    connect(server,&QTcpSocket::readyRead,this,&TD3650ClientThread::waitRead);


    sendData(天恒生成帧("PARW|OUTSW=ON"));//用来确认是否连接成功


    emit TD3650State("正在连接TD3650",true,0);
    timer1->start(2000);
  //  qDebug()<<"通讯正常getConj"<<IP地址<<IP端口;
  //  qDebug()<<"TD3650当前线程"<<QThread::currentThread();
}

//确认与TD3650连接成功
void TD3650ClientThread::confirmTD3650()
{

    timer1->stop();
    qDebug()<<"配置3650通讯"<<接收数据;

    if(接收数据=="Net Init OK"||接收数据=="PARW=00")
    {
        //  qDebug()<<"通讯正常"<<接收数据;
        网口状态=1;
        sendData(天恒生成帧("OUT|UA=50|UB=50|UC=50|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=0|IB=0|IC=0"));sleepMsec(200);
        sendData(天恒生成帧("PARW|OUTSW=ON"));sleepMsec(5000);
        emit TD3650State("开始校准",true,1);
        sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=0|IB=0|IC=0"));
        return;
    }

    if(接收数据.length()==0)
    {
        网口状态=3;
        emit TD3650State("TD3650没接收到数据",false,100); return;
    }


    if(错误类型==0) { emit TD3650State("TD3650未接收到数据",false,100); return;}
    if(错误类型==2) { emit TD3650State("TD3650校验错误",false,100);    return;}
    if(错误类型==10){ emit TD3650State("TD3650接收的数据长度错误",false,100);return;}

}

void TD3650ClientThread::calibrate_TD3650(int 校准步骤)
{
    //sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=0|IB=0|IC=0"));
    qDebug()<<"TD3650校准步骤"<<校准步骤;

    if(校准步骤==101){//只能由主线程发送 校准步骤==100, 表示停止校准, 关闭串口

        disconnect(server,&QTcpSocket::readyRead,this,&TD3650ClientThread::waitRead);
        if(网口状态==1||网口状态==3)
        {
            if(网口状态==1)
            {
            sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(200);
            sendData(天恒生成帧("PARW|ACIRG=AUTO"));sleepMsec(200);
            sendData(天恒生成帧("PARW|OUTSW=OFF"));sleepMsec(200);
            }
            server->close();
            server->deleteLater();
        }
        qDebug()<<"TD3650当前线程100"<<QThread::currentThread();
        if(TD校准步骤==12) emit TD3650State("TD3650校准完成",false,101);
        if(TD校准步骤<12) emit TD3650State("TD3650校准异常结束",false,101);
        网口状态=0;
        TD校准步骤=1;

        return;
    }

    TD校准步骤=校准步骤;


//qDebug()<<"TD校准步骤aaa"<<TD校准步骤;
   //  timer2->start(5000);//不停地检查源的输出是否达到要求


     switch(TD校准步骤)
     {
     case 2: sendData(天恒生成帧("PARW|ACIRG=AC1A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=0|IB=0|IC=0"));     break;// timer2->start(5000); break;//[cal_0] 初始化

     case 3: sendData(天恒生成帧("PARW|ACIRG=AC100A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=2|IB=2|IC=2"));sleepMsec(5000);//先输个小电流，如果有开路，则先保护，就不会在80A的时候才保护了
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=80|IB=80|IC=80"));  break;// timer2->start(25000);break;//[cal_1] 80A,PF=1

     case 4: //sendData(天恒生成帧("PARW|ACIRG=AC100A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=60|PHUBIB=60|PHUCIC=60|IA=80|IB=80|IC=80"));break;//timer2->start(25000);break;//[cal_2] 80A,PF=0.5

     case 5: sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(5000);
             sendData(天恒生成帧("PARW|ACIRG=AC50A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=20|IB=20|IC=20"));  break;// timer2->start(18000);break;//[cal_3] 20A,PF=1

     case 6: //sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(1000);
             //sendData(天恒生成帧("PARW|ACIRG=AC50A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=60|PHUBIB=60|PHUCIC=60|IA=20|IB=20|IC=20"));break;//timer2->start(18000);break;//[cal_4] 20A,PF=0.5

     case 7: sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(5000);
             sendData(天恒生成帧("PARW|ACIRG=AC5A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=5|IB=5|IC=5"));     break;// timer2->start(18000);break;//[cal_5] 5A,PF=1

     case 8: //sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(200);
             //sendData(天恒生成帧("PARW|ACIRG=AC5A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=60|PHUBIB=60|PHUCIC=60|IA=5|IB=5|IC=5")); break;//  timer2->start(18000);break;//[cal_6] 5A,PF=0.5

     case 9: sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(1000);
             sendData(天恒生成帧("PARW|ACIRG=AC2A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=1|IB=0|IC=0"));    break;//  timer2->start(15000);break;//[cal_7] 1A,漏电

     case 10://sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(200);
             //sendData(天恒生成帧("PARW|ACIRG=AC2A"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=60|PHUBIB=60|PHUCIC=60|IA=2|IB=2|IC=2"));  break;// timer2->start(15000);break;//[cal_8] 2A,偏置

     case 11:sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(200);
             sendData(天恒生成帧("PARW|ACIRG=AUTO"));sleepMsec(200);
             sendData(天恒生成帧("OUT|UA=220|UB=220|UC=220|PHUAIA=0|PHUBIB=0|PHUCIC=0|IA=0|IB=0|IC=0"));    break;//  timer2->start(5000); break;//输出全设0,停止校准

     case 12:sendData(天恒生成帧("PARW|OUTSW=OFF"));emit TD3650State("全部校准完成",false,12);break;//关闭输出

     default: emit TD3650State("全部校准完成",false,100);
     }

    qDebug()<<"TD校准步骤TDTD"<<TD校准步骤;

    //源的标准值
    switch(TD校准步骤)
    {
    case 2: TD4550输出={220000,220000,220000,     0,     0,     0,       0,       0,       0,      0,      0,      0,       0,       0,       0,       0,       0,       0};break;
    case 3: TD4550输出={220000,220000,220000, 80000, 80000, 80000,17600000,17600000,17600000,1000000,1000000,1000000,       0,       0,       0,17600000,17600000,17600000};break;
    case 4: TD4550输出={220000,220000,220000, 80000, 80000, 80000, 8800000, 8800000, 8800000, 500000, 500000, 500000,15242047,15242047,15242047,17600000,17600000,17600000};break;
    case 5: TD4550输出={220000,220000,220000, 20000, 20000, 20000, 4400000, 4400000, 4400000,1000000,1000000,1000000,       0,       0,       0, 4400000, 4400000, 4400000};break;
    case 6: TD4550输出={220000,220000,220000, 20000, 20000, 20000, 2200000, 2200000, 2200000, 500000, 500000, 500000, 3810512, 3810512, 3810512, 4400000, 4400000, 4400000};break;
    case 7: TD4550输出={220000,220000,220000,  5000,  5000,  5000, 1100000, 1100000, 1100000,1000000,1000000,1000000,       0,       0,       0, 1100000, 1100000, 1100000};break;
    case 8: TD4550输出={220000,220000,220000,  5000,  5000,  5000,  550000,  550000,  550000, 500000, 500000, 500000,  952628,  952628,  952628, 1100000, 1100000, 1100000};break;
    case 9: TD4550输出={220000,220000,220000,  1000,    0,      0,  220000,       0,       0,1000000,      0,      0,       0,       0,       0, 2200000,       0,       0};break;
    case 10:TD4550输出={220000,220000,220000,  2000,  2000,  2000,  220000,  220000,  220000, 500000, 500000, 500000,  381051,  381051,  381051,  440000,  440000,  440000};break;
    case 11:TD4550输出={220000,220000,220000,     0,     0,     0,       0,       0,       0,      0,      0,      0,       0,       0,       0,       0,       0,       0};break;
   // default: break;
    }


}


//不停地检查源的输出是否达到要求
void TD3650ClientThread::TD3650Step()
{
    qDebug()<<"TD3650在30秒后";

    QString 校准信息="源的步骤 "+QString::number(TD校准步骤,10)+"已准备好。";

    switch(TD校准步骤)
    {
    case 2 :校准信息 +="220V, 0A偏置";break;
    case 3 :校准信息 +="220V, 80A, PF=1";break;
    case 4 :校准信息 +="220V, 80A, PF=0.5";break;
    case 5 :校准信息 +="220V, 20A, PF=1";break;
    case 6 :校准信息 +="220V, 20A, PF=0.5";break;
    case 7 :校准信息 +="220V, 5A, PF=1";break;
    case 8 :校准信息 +="220V, 5A, PF=0.5";break;
    case 9 :校准信息 +="220V,漏电流1A";break;
    case 10 :校准信息 +="220V, 2A, PF=0.5, 偏置";break;
    case 11 :校准信息 +="样机恢复出厂参数";break;
    default:break;
    }

   // timer2->stop();
    emit TD3650State(校准信息,true,TD校准步骤);
}


void TD3650ClientThread::检查源输出(QString 接收数据)
{

    if(接收数据=="PARW=00") {检查步骤=1;检查次数=1;}
    if(接收数据=="OUT=00") {检查步骤=1;检查次数=1;}
    qDebug()<<"接收数据"<<接收数据;
    qDebug()<<"检查步骤"<<检查步骤<<"TD4550当前检查次数"<<检查次数;

    if(检查次数)
    {

        int32_t 测量值;
        char 类型='0';
        测量值=天恒转int32(&类型,接收数据);
        qDebug()<<"测量值"<<测量值<<"TTD4550输出.电压A"<<TD4550输出.电压B;

        switch(检查步骤)
        {
        case 1:if(测量值>(TD4550输出.电压A-200) && 测量值<(TD4550输出.电压A+200)){检查步骤++;检查次数=1;};break;
        case 2:if(测量值>(TD4550输出.电压B-200) && 测量值<(TD4550输出.电压B+200)){检查步骤++;检查次数=1;};break;
        case 3:if(测量值>(TD4550输出.电压C-200) && 测量值<(TD4550输出.电压C+200)){检查步骤++;检查次数=1;};break;
        case 4:if(测量值>(TD4550输出.电流A-200) && 测量值<(TD4550输出.电流A+200)){检查步骤++;检查次数=1;};break;
        case 5:if(测量值>(TD4550输出.电流B-150) && 测量值<(TD4550输出.电流B+150)){检查步骤++;检查次数=1;};break;
        case 6:if(测量值>(TD4550输出.电流C-100) && 测量值<(TD4550输出.电流C+100)){检查步骤++;检查次数=1;};break;
        case 7:if(测量值>(TD4550输出.功率A-2000) && 测量值<(TD4550输出.功率A+2000)){检查步骤++;检查次数=1;};break;//17599620=17.6KW
        case 8:if(测量值>(TD4550输出.功率B-2000) && 测量值<(TD4550输出.功率B+2000)){检查步骤++;检查次数=1;};break;
        case 9:if(测量值>(TD4550输出.功率C-2000) && 测量值<(TD4550输出.功率C+2000)){检查步骤++;检查次数=1;};break;
        }
    }

    检查次数++;


    if(检查次数>50) {
        sendData(天恒生成帧("OUT|IA=0|IB=0|IC=0"));sleepMsec(200);
        sendData(天恒生成帧("PARW|ACIRG=AUTO"));sleepMsec(200);
        sendData(天恒生成帧("PARW|OUTSW=OFF"));sleepMsec(200);
        emit TD3650State("源输出不正常",false,100); return;
    }
    if(检查步骤>9) {TD3650Step();检查步骤=1;检查次数=1;return;}//6个步骤都检查正常,发送正常信号给主线程

    sleepMsec(500);

    switch(检查步骤)
    {
    case 1:sendData(天恒生成帧("MEAS|UA"));break;
    case 2:sendData(天恒生成帧("MEAS|UB"));break;
    case 3:sendData(天恒生成帧("MEAS|UC"));break;
    case 4:sendData(天恒生成帧("MEAS|IA"));break;
    case 5:sendData(天恒生成帧("MEAS|IB"));break;
    case 6:sendData(天恒生成帧("MEAS|IC"));break;
    case 7:sendData(天恒生成帧("MEAS|PA"));break;//因为TD3650在电流为0时，功率因数会是个随机数，所以改成功率判定。
    case 8:sendData(天恒生成帧("MEAS|PB"));break;
    case 9:sendData(天恒生成帧("MEAS|PC"));break;
    }



}





//发送数据到串口
void TD3650ClientThread::sendData(QByteArray data)
{
   qDebug()<<"发送数据到3650网口"<<data;
   server->write(data);//数据传输入服务器
}

//读取接收到的信息
void TD3650ClientThread::ReadData()
{
    QByteArray buf;
    buf = server->readAll();

    if(!buf.isEmpty())//buf读到内容，才会上传数据到窗口,不保证能把数据完全读完
    {
       接收数据=天恒还原帧(buf,&错误类型);
       qDebug()<<"3650接收到数据"<<接收数据;
       if(TD校准步骤>1) 检查源输出(接收数据);
    }
}

//当&QSerialPort::readyRead发送信号说准备要开始读了，则执行此定时函数，不能用sleep()
void TD3650ClientThread::waitRead()
{
     QTimer::singleShot(BaudTime, this,&TD3650ClientThread::ReadData);
}

